package com.study.spmongodb.wwj.thread.char13;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @author MI
 * @version 1.0
 * @date 2020/12/6 18:04
 */
public class SimpleThreadPool {
    /**
     * 任务队列
     * 拒绝策略(抛出异常，直接丢弃，阻塞，临时队列)
     * init(min)
     * active
     * max
     * min<= active<=max
     */

    private final int size;
    private final static int DEFAULT_SIZE = 10;
    private static volatile int seq = 0;

    private static final String THREAD_PREFIX = "SIMPLE_POOL_";

    private final static ThreadGroup GROUP = new ThreadGroup("POOL_GROUP");
    private final static LinkedList<Runnable> TASKQUQUQ = new LinkedList<>();

    private final static List<WorkTask> THREAD_QUEUE = new ArrayList<>();

    public SimpleThreadPool() {
        this(DEFAULT_SIZE);
    }

    public SimpleThreadPool(int size) {
        this.size = size;
        init();
    }

    private void init() {
        for (int i = 0; i < size; i++) {
            createWorkTask();
        }
    }

    public void submit(Runnable runnable) {
        synchronized (TASKQUQUQ) {
            TASKQUQUQ.addLast(runnable);
            TASKQUQUQ.notifyAll();
        }
    }

    private void createWorkTask() {
        final WorkTask workTask = new WorkTask(GROUP, THREAD_PREFIX + (seq++));
        workTask.start();
        THREAD_QUEUE.add(workTask);
    }

    private enum TaskState {
        FREE, RUNNING, BLOCKED, DEAD
    }

    private static class WorkTask extends Thread {

        private volatile TaskState taskState = TaskState.FREE;

        public WorkTask(ThreadGroup group, String name) {
            super(group, name);
        }

        @Override
        public void run() {
            OUTER:
            while (this.taskState != TaskState.DEAD) {
                Runnable runnable;
                synchronized (TASKQUQUQ) {
                    while (TASKQUQUQ.isEmpty()) {
                        try {
                            taskState = TaskState.BLOCKED;
                            TASKQUQUQ.wait();
                        } catch (InterruptedException e) {
                            break OUTER;
                        }
                    }
                    runnable = TASKQUQUQ.removeFirst();
                }
                if (runnable != null) {
                    taskState = TaskState.RUNNING;
                    runnable.run();
                    taskState = TaskState.FREE;
                }
            }
        }

        public TaskState getTaskState() {
            return this.taskState;
        }

        public void close() {
            this.taskState = TaskState.DEAD;
        }
    }

    public static void main(String[] args) {
        final SimpleThreadPool pool = new SimpleThreadPool();

        IntStream.range(0, 40)
                .forEach(i -> pool.submit(() -> {
                    System.out.println(i + "- 当前线程是" + Thread.currentThread().getName()
                    );
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(i + "  finished");
                }));
    }
}
